package com.yeziji.common.business.system.service.impl;

import com.yeziji.common.CommonErrorMsg;
import com.yeziji.common.IServiceImpl;
import com.yeziji.common.business.system.SystemConfigConvertor;
import com.yeziji.common.business.system.constant.SystemConfigTypeInterface;
import com.yeziji.common.business.system.constant.enums.SystemConfigTypeEnum;
import com.yeziji.common.business.system.dto.SystemEmailConfigDTO;
import com.yeziji.common.business.system.entity.SystemConfigEntity;
import com.yeziji.common.business.system.mapper.SystemConfigMapper;
import com.yeziji.common.business.system.msg.SystemErrorMsg;
import com.yeziji.common.business.system.service.SystemConfigService;
import com.yeziji.utils.expansion.Asserts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.function.Function;

/**
 * 系统配置表 服务层实现。
 *
 * @author system
 * @since 2023-11-13
 */
@Slf4j
@Service
public class SystemConfigServiceImpl extends IServiceImpl<SystemConfigMapper, SystemConfigEntity> implements SystemConfigService {
    @Autowired(required = false)
    private JavaMailSender javaMailSender;

    @PostConstruct
    public void init() {
        try {
            SystemEmailConfigDTO emailConfig = this.getEmailConfig();
            if (emailConfig != null) {
                this.updateEmailConfig(emailConfig);
            }
        } catch (Exception e) {
            log.error("初始化配置异常: {}", e.getMessage());
        }
    }

    @Override
    public boolean saveEmailConfig(SystemEmailConfigDTO emailConfigDTO) {
        SystemConfigEntity emailConfig = this.getByTypeEnum(SystemConfigTypeEnum.EMAIL);
        if (emailConfig != null) {
            emailConfig.setConfigValue(SystemConfigConvertor.objConvertToStr(emailConfigDTO));
        } else {
            emailConfig =
                    SystemConfigEntity.builder()
                            .configType(SystemConfigTypeEnum.EMAIL.getCode())
                            .configValue(SystemConfigConvertor.objConvertToStr(emailConfigDTO))
                            .build();
        }
        // 动态更新配置
        this.updateEmailConfig(emailConfigDTO);
        return this.saveOrUpdate(emailConfig);
    }

    @Override
    public SystemEmailConfigDTO getEmailConfig() {
        return this.getByTypeEnumThrowThen(SystemConfigTypeEnum.EMAIL, SystemConfigConvertor::buildEmailConfig);
    }

    @Override
    public SystemConfigEntity getByTypeEnum(SystemConfigTypeEnum configTypeEnum) {
        return this.queryChain()
                .where(SystemConfigEntity::getConfigType).eq(configTypeEnum.getCode())
                .one();
    }

    @Override
    public <T> boolean saveConfig(T config, SystemConfigTypeInterface typeInterface) {
        Asserts.notNull(typeInterface, CommonErrorMsg.REQUIRED_DATA_IS_NULL);
        SystemConfigEntity entity = this.getByCode(typeInterface);
        String configStr = SystemConfigConvertor.objConvertToStr(config);
        if (entity != null) {
            entity.setConfigValue(configStr);
        } else {
            entity = SystemConfigEntity.builder()
                    .configType(typeInterface.getCode())
                    .configValue(configStr)
                    .build();
        }
        return this.saveOrUpdate(entity);
    }

    @Override
    public <T> T getConfigByTypeAndConvertFn(SystemConfigTypeInterface typeInterface, Function<String, T> function) {
        SystemConfigEntity entity = Asserts.notNull(this.getByCode(typeInterface), SystemErrorMsg.SYSTEM_CONFIG_IS_NOT_EXISTS);
        return function.apply(entity.getConfigValue());
    }

    @Override
    public SystemConfigEntity getByCode(SystemConfigTypeInterface typeInterface) {
        return this.queryChain()
                .where(SystemConfigEntity::getConfigType).eq(typeInterface.getCode())
                .one();
    }

    /**
     * 根据配置枚举获取其对象值
     *
     * @param configTypeEnum 配置枚举
     * @param function       转换行为
     * @param <T>            指定转化泛型
     * @return {@link T} 指定转化泛型对象
     */
    private <T> T getByTypeEnumThrowThen(SystemConfigTypeEnum configTypeEnum, Function<SystemConfigConvertor, T> function) {
        SystemConfigEntity systemConfigEntity =
                Asserts.notNull(this.getByTypeEnum(configTypeEnum), SystemErrorMsg.SYSTEM_CONFIG_IS_NOT_EXISTS);
        return function.apply(SystemConfigConvertor.init(systemConfigEntity.getConfigValue()));
    }

    /**
     * 更新 email 配置
     */
    private void updateEmailConfig(SystemEmailConfigDTO emailConfig) {
        // update java mail
        if (javaMailSender != null) {
            JavaMailSenderImpl javaMailSenderImpl = (JavaMailSenderImpl) javaMailSender;
            javaMailSenderImpl.setHost(emailConfig.getHost());
            javaMailSenderImpl.setUsername(emailConfig.getUsername());
            javaMailSenderImpl.setPassword(emailConfig.getPassword());
        }
    }
}
